package dan.frontend
import chisel3._
import chisel3.util._
import dan.common.CoreModule
import dan.common.SDPRam
import dan.utility._

class RASIO extends Bundle with HasBPUParam{
    val readIdx = Input(UInt(log2Ceil(rasSize).W))
    val readTarget = Output(UInt(targetBits.W))
    val wrValid = Input(Bool())
    val wrIdx = Input(UInt(log2Ceil(rasSize).W))
    val wrTarget = Input(UInt(targetBits.W))
}

class RAS extends Module with HasBPUParam{
    val io = IO(new RASIO())
    val ras = Module(new SDPRam(rasSize, UInt(targetBits.W)))
    ras.io.raddr := io.readIdx
    io.readTarget := ras.io.rdata.head
    ras.io.wen := io.wrValid
    ras.io.waddr := io.wrIdx
    ras.io.wdata.head := io.wrTarget
    ras.io.wstrobe := 1.U
}

class RASIdx extends Bundle with HasBPUParam{
    val bits = UInt(log2Ceil(rasSize).W)
    def update(en: Bool, isCall: Bool, isRet: Bool): RASIdx = {
        val newPtr = Wire(new RASIdx())
        newPtr.bits := Mux(en && isCall, WrapInc(bits, rasSize), Mux(en && isRet, WrapDec(bits, rasSize), bits))
        newPtr
    }
}

